/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.controller.admin;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.request.admin.ResourceSaveRequestMessage;
import cn.easyplatform.messages.request.admin.ServiceRequestMessage;
import cn.easyplatform.messages.vos.admin.ResourceVo;
import cn.easyplatform.messages.vos.admin.ServiceVo;
import cn.easyplatform.spi.service.AdminService;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.type.ServiceType;
import cn.easyplatform.type.StateType;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.dialog.MessageBox;
import cn.easyplatform.web.service.ServiceLocator;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.*;

import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class DatasourceController extends SelectorComposer<Component> {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    private ResourceVo rv;

    @Wire("combobox#ds")
    private Combobox ds;

    @Wire("button#serviceOp")
    private Button serviceOp;

    @Wire("button#restart")
    private Button restart;

    @Wire("label#startTime")
    private Label startTime;

    @Wire("listbox#dsProperties")
    private Listbox dsProperties;

    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        AdminService as = ServiceLocator.lookup(AdminService.class);
        IResponseMessage<?> resp = as.getData(new SimpleRequestMessage(ServiceType.DATASOURCE));
        if (resp.isSuccess()) {
            List<ResourceVo> list = (List<ResourceVo>) resp.getBody();
            if (list.size() > 1) {
                for (ResourceVo s : list) {
                    Comboitem item = new Comboitem();
                    item.setLabel(s.getId());
                    item.setDescription(s.getName());
                    item.setValue(s);
                    ds.appendChild(item);
                }
                ds.setSelectedIndex(0);
                select(list.get(0));
            } else {
                select(list.remove(0));
                ds.getPreviousSibling().detach();
                ds.detach();
            }
        } else {
            MessageBox.showMessage(resp);
            comp.detach();
        }
    }

    private void select(ResourceVo rb) {
        this.rv = rb;
        Listitem item = new Listitem();
        item.appendChild(new Listcell("ID"));
        item.appendChild(new Listcell(rv.getId()));
        item.setParent(dsProperties);
        item = new Listitem();
        item.appendChild(new Listcell(Labels.getLabel("admin.project.name")));
        Textbox tb = new Textbox(rv.getName());
        tb.setHflex("1");
        tb.setInplace(true);
        Listcell cell = new Listcell();
        cell.appendChild(tb);
        item.appendChild(cell);
        item.setParent(dsProperties);
        for (Map.Entry<String, String> entry : rv.getProps().entrySet()) {
            item = new Listitem();
            item.appendChild(new Listcell(entry.getKey()));
            cell = new Listcell();
            tb = new Textbox();
            tb.setHflex("1");
            tb.setInplace(true);
            if ("password".equals(entry.getKey())) {
                tb.setValue(StringUtils.overlay(entry.getValue(), StringUtils.repeat('*', entry.getValue().length() - 2), 1, entry.getValue().length() - 1));
            } else {
                tb.setValue(entry.getValue());
            }
            cell.appendChild(tb);
            item.appendChild(cell);
            dsProperties.appendChild(item);
        }
        setState();
        setRtInfo(rv.getStartTime());
    }

    private void setRtInfo(Date date) {
        if (date != null) {
            startTime.setValue(Labels.getLabel("service.start.time") + " : " + DateFormatUtils.format(date,
                    "yyyy-MM-dd hh:mm:ss"));
        } else
            startTime.setValue(null);
        rv.setStartTime(date);
    }

    private void setState() {
        restart.setDisabled(StateType.STOP == rv.getState());
        if (!restart.isDisabled()) {
            serviceOp.setLabel(Labels.getLabel("admin.service.stop"));
            serviceOp.setIconSclass("z-icon-cog z-icon-spin");
            serviceOp.setTooltiptext(Labels
                    .getLabel("admin.service.stop.tooltip"));
        } else {
            serviceOp.setLabel(Labels.getLabel("admin.service.start"));
            serviceOp.setIconSclass("z-icon-play");
            serviceOp.setTooltiptext(Labels
                    .getLabel("admin.service.start.tooltip"));
        }
    }

    @Listen("onSelect=#ds")
    public void onSelect() {
        ResourceVo vo = ds.getSelectedItem().getValue();
        dsProperties.getItems().clear();
        select(vo);
    }

    @Listen("onClick=#restart")
    public void onRestart() {
        Messagebox.show(Labels.getLabel("admin.service.op.confirm",
                new Object[]{Labels.getLabel("admin.service.restart")}), Labels
                        .getLabel("admin.service.op.title"), Messagebox.CANCEL
                        | Messagebox.OK, Messagebox.QUESTION,
                new EventListener<Event>() {

                    @Override
                    public void onEvent(Event evt) throws Exception {
                        if (evt.getName().equals(Messagebox.ON_OK)) {
                            AdminService as = ServiceLocator
                                    .lookup(AdminService.class);
                            IResponseMessage<?> resp = as
                                    .setServiceState(new ServiceRequestMessage(
                                            new ServiceVo(rv.getId(), ServiceType.DATASOURCE, StateType.RESUME)));
                            if (resp.isSuccess()) {
                                if (resp.getBody() != null) {
                                    Date rt = (Date) resp.getBody();
                                    setRtInfo(rt);
                                } else {
                                    rv.setState(StateType.STOP);
                                    setState();
                                    setRtInfo(null);
                                }
                            } else {
                                rv.setState(StateType.STOP);
                                setState();
                                setRtInfo(null);
                                MessageBox.showMessage(resp);
                            }
                        }
                    }
                });
    }

    @Listen("onClick=#serviceOp")
    public void onServiceOp() {
        String msg = null;
        if (rv.getState() == StateType.STOP) {
            msg = Labels.getLabel("admin.service.start");
        } else {
            msg = Labels.getLabel("admin.service.stop");
        }
        if (!Contexts.getUser().getId().equals(rv.getId())) {
            Messagebox.show(Labels.getLabel("admin.service.op.confirm",
                    new Object[]{msg}), Labels
                            .getLabel("admin.service.op.title"), Messagebox.CANCEL
                            | Messagebox.OK, Messagebox.QUESTION,
                    new EventListener<Event>() {

                        @Override
                        public void onEvent(Event evt) throws Exception {
                            if (evt.getName().equals(Messagebox.ON_OK)) {
                                if (rv.getState() == StateType.STOP)
                                    rv.setState(StateType.START);
                                else
                                    rv.setState(StateType.STOP);
                                AdminService as = ServiceLocator
                                        .lookup(AdminService.class);
                                IResponseMessage<?> resp = as
                                        .setServiceState(new ServiceRequestMessage(
                                                new ServiceVo(rv.getId(), ServiceType.DATASOURCE, rv.getState())));
                                if (resp.isSuccess()) {
                                    setState();
                                    if (resp.getBody() != null) {
                                        Date rt = (Date) resp.getBody();
                                        setRtInfo(rt);
                                    } else {
                                        rv.setState(StateType.STOP);
                                        setState();
                                        setRtInfo(null);
                                    }
                                } else {
                                    MessageBox.showMessage(resp);
                                }
                            }
                        }
                    });
        } else
            MessageBox.showMessage(
                    Labels.getLabel("admin.service.op.title"),
                    Labels.getLabel(
                            "admin.service.op.self",
                            new Object[]{rv.getId(),
                                    Labels.getLabel("admin.service.stop")}));
    }

    @Listen("onClick=#add")
    public void onAdd() {
        Listitem item = new Listitem();
        Listcell cell = new Listcell();
        Textbox tb = new Textbox("key");
        tb.setHflex("1");
        tb.setInplace(true);
        cell.appendChild(tb);
        cell.setParent(item);
        cell = new Listcell();
        tb = new Textbox("value");
        tb.setHflex("1");
        tb.setInplace(true);
        cell.appendChild(tb);
        cell.setParent(item);
        dsProperties.appendChild(item);
    }

    @Listen("onClick=#save")
    public void onSave(Event evt) {
        List<Listitem> items = dsProperties.getItems();
        rv.setName(((Textbox) dsProperties.getItemAtIndex(1).getLastChild().getFirstChild()).getValue());
        for (int i = 2; i < items.size(); i++) {
            Listitem li = items.get(i);
            Listcell cell = (Listcell) li.getFirstChild();
            String name = null;
            if (cell.getFirstChild() == null)
                name = cell.getLabel();
            else
                name = ((Textbox) cell.getFirstChild()).getValue();
            cell = (Listcell) li.getLastChild();
            Textbox tb = (Textbox) cell.getFirstChild();
            // 空值去掉
            if (Strings.isBlank(name) || Strings.isBlank(tb.getValue()))
                rv.getProps().remove(name);
            else {
                if ("password".equals(name)) {
                    String password = tb.getValue().substring(1, tb.getValue().length() - 1);
                    if (!StringUtils.repeat('*', tb.getValue().length() - 2).equals(password))
                        rv.getProps().put(name, tb.getValue());
                } else
                    rv.getProps().put(name, tb.getValue());
            }
        }
        AdminService as = ServiceLocator.lookup(AdminService.class);
        IResponseMessage<?> resp = as.saveResource(new ResourceSaveRequestMessage(rv));
        if (resp.isSuccess()) {
            Button btn = (Button) evt.getTarget();
            MessageBox.showInfo(Labels.getLabel("admin.service.op.title"), Labels.getLabel("common.success", new String[]{btn.getLabel()}));
        } else
            MessageBox.showMessage(resp);
    }

    @Listen("onClick=#remove")
    public void onRemove() {
        final Listitem li = dsProperties.getSelectedItem();
        if (li == null)
            return;
        String name = null;
        Listcell cell = (Listcell) li.getFirstChild();
        if (cell.getFirstChild() == null)
            name = cell.getLabel();
        else
            name = ((Textbox) cell.getFirstChild()).getValue();
        Messagebox.show(Labels.getLabel("admin.service.op.confirm",
                new Object[]{Labels.getLabel("admin.project.property.remove")
                        + name}), Labels.getLabel("admin.service.op.title"),
                Messagebox.CANCEL | Messagebox.OK, Messagebox.QUESTION,
                new EventListener<Event>() {

                    @Override
                    public void onEvent(Event evt) throws Exception {
                        if (evt.getName().equals(Messagebox.ON_OK)) {
                            li.detach();
                        }
                    }
                });
    }
}
